(function($) {
    $.loadJs = function (url) {
	var s;
	if (url instanceof Object)
		s = url;
	else {
		s = document.createElement("script");
		s.src = url;//+'?'+(Math.random()+'').substr(2);
		s.type="text/javascript";
	}
	document.getElementsByTagName("head")[0].appendChild(s);
    };
    $.loadCss = function(url) {
             	var c;
		if (url instanceof Object)
			c = url;
		else {
			c = document.createElement("link");
			c.href = url;
			c.type="text/css";
                        c.media = "screen";
                        c.rel = "stylesheet";
		}
		document.getElementsByTagName("head")[0].appendChild(c);
    };
    $.dialogo = function(opts) {
        var opts= opts || {};
        var div= $('<div>'+opts.mensaje+'</div>');
	if (!opts.buttons)
	    opts.buttons = {"Cerrar" : function() {var d = $(this);d.dialog('destroy');d.remove();}};
        delete(opts.mensaje);
        opts.title = opts.titulo;
        delete(opts.titulo);
        div.attr(opts);
        delete(opts.title);
        if (!opts.modal) opts.modal=true;
        if (!opts.closeOnScape) opts.closeOnScape= true;
        if (opts.data!=undefined)
            div.data(opts.data);
        div.dialog(opts);
    };
    $.confirmar = function(opciones,callback) {
        opciones = opciones || {};
        if (opciones.botones) 
            opciones.buttons = opciones.botones;
        else {
            opciones.buttons ={};
            opciones.buttons[i18n("confirmar", "boton-cancelar")]=function() {
                $('#ajax-wait').dialog('close');
                $(this).dialog('close');
            };
            opciones.buttons[i18n("confirmar", "boton-confirmar")]=function() {
                $('#ajax-wait').dialog('close');
                $(this).data('callback').call(this);
                $(this).dialog('close');
            };
        }
        opciones = jQuery.extend({}, { 
            "dialogClass": "dialogo",
            "modal": true,
            "titulo" : i18n("confirmar", "titulo-defecto"),
            "texto": i18n("confirmar", "mensaje-defecto"),
            "width": 500,
            "height": "auto",
            "close" : function() {$('#dialogo_confirmar').dialog('destroy').remove();}
        }, opciones);
        var div = $('<div id="dialogo_confirmar" title="'+opciones.titulo+'">'+opciones.texto+'</div>')
        div.dialog(opciones);
        if (!callback)
            div.data('callback', opciones.close);
        else
            div.data('callback', callback);
    };
    $.fn.lista = (function (url, map, options) {
        var ts = $(this);
        if (!options) options = {};
        if (['anterior', 'cargar', 'siguiente', 'getData', 'url'].indexOf(url) > -1) {
            var args;
            for (i in arguments) {
                if (i==0) continue;
                args.push(arguments[i]);
            }
            return $.fn.lista[url].apply(this, args);
        }
        options.rowsNum = options.rowsNum || 10;
	options.load = options.load || '$.fn.lista.cargar';
        ts.data("url", url);
	ts.data("load", options.load);
        ts.data("map", map);
        options.page = 1;
        if (options.control)
            options.control = options.control;
        ts.data("options", options);
        ts.data("count", {records: 0, pages: 1});
        ts.html($('<thead></thead><tfoot></tfoot><tbody></tbody>'));
        $.fn.lista._header.apply(ts);
        $.fn.lista._footer.apply(ts);
	var load = eval(options.load);
        load.apply(this, [ function(ts){$.fn.lista._update_footer.apply(ts);}]);
        ts.addClass('ui-lista');
        return ts;
    });
    $.extend($.fn.lista, {
        url: function () {
            return $(this).data("url");
        },
        _header: function () {
            var label, th;
            var map = this.data("map");
            var thead = this.children('thead');
            var options = this.data("options");
            var order = {"by": options.orderby, "direction": options.orderdir};
            var header = $('<tr class="ui-lista-header"></tr>');
            for (var a in map) {
                if (map[a].key && !map[a].show) continue;
                if(map[a].label) label = map[a].label; else label=a;
                th = $('<th id="'+a+'" sortable="'+(map[a].sortable!==false?"true":"false")+'">'+label+'<span class="ui-lista-direccion"></span></th>');
                if (order.by == a) {
                    th.attr("sorted", order.direction);
                    th.children('.ui-lista-direccion').addClass(order.direction);
                }
                header.append(th);
            }
            $('th[sortable=true]', header).click (function () {
                var ts = $(this);
                var table = ts.parents('table');
                var parent = ts.parents('table');
                var ad = ['asc', 'desc', '', 'asc'];
                var sorted = ad[ad.indexOf((ts.attr('sorted') || ''), ad)+1];
                var siblings = ts.parent().children('*');
                siblings.removeAttr('sorted');
                $(".ui-lista-direccion", siblings).removeClass('asc').removeClass('desc');
                $('tr', table).removeClass('highlight');
                if (ts.control)
                    ts.control('remove');
                if (sorted) {
                    ts.attr('sorted', sorted);
                    ts.children('span').addClass(sorted);
                }
                parent.data("options", jQuery.extend(parent.data("options"), {"orderby": ts.attr('id'), "orderdir": sorted}));
                var load = eval(table.data('load'));
                load.apply(parent.get(0));
            });
            thead.append(header);
        },
        _footer: function () {
            var i, c=0, tfoot = this.children('tfoot');
            for (i in this.data("map"))
                c++;
            var tr = $('<tr class="ui-lista-pager"><td colspan='+c+'><div id="'+this.attr('id')+'-pager"><input type="button" class="ui-lista-boton-anterior ui-lista-boton" disabled="disabled" value="<<"/> <input class="ui-lista-input" type="text" size="2" value="1"> de <span class="ui-lista-cantidad-paginas">'+this.data("count").pages+'</span> <input type="button" class="ui-lista-boton-siguiente ui-lista-boton" value=">>"/></div></td></tr>');
            tfoot.append(tr);
            $('.ui-lista-boton-anterior', tr).click(function(e){$(e.target).parents('table').lista('anterior');});
            $('.ui-lista-boton-siguiente', tr).click(function(e){$(e.target).parents('table').lista('siguiente');});
        },
        _update_footer: function () {
            $('.ui-lista-cantidad-paginas', this).html(this.data("count").pages);
        },
        anterior: function () {
            var ts = $(this);
            if ((ts.data("options").page-1) > 0 ) {
                $.fn.lista._menos.apply(ts);
                $.fn.lista.cargar.apply(this);
            }
            return ts
        },
        siguiente : function () {
            var ts = $(this);
            if ((ts.data("options").page+1) <= ts.data("count").pages ) {
                $.fn.lista._mas.apply(ts);
                $.fn.lista.cargar.apply(this);
            }
            return ts
        },
        _mas : function(){
            return $.fn.lista._cambiar(this, 1);
        },
        _menos: function(){
            return $.fn.lista._cambiar(this, -1);
        },
        _cambiar: function(ts, s){
            var boton;
            var options = ts.data("options");
            options.page+=s;
            $('.ui-lista-input', ts).val(options.page);
            ts.data("options", options);
            boton = $('.ui-lista-boton-siguiente', ts);
            if (ts.data("count").pages==options.page)
                boton.attr('disabled', 'disabled');
            else
                boton.removeAttr('disabled');
            boton = $('.ui-lista-boton-anterior', ts)
            if (options.page == 1)
                boton.attr('disabled', 'disabled');
            else
                boton.removeAttr('disabled');
        },
        _fetch: function (rows) {
            var key, tr, val, attr;
            var map = this.data("map");
            var tbody = this.children('tbody');
            for (i in rows) {
                if (i=='indexOf') continue;
                key = [];
                tr = $('<tr class="ui-lista-fila-'+((i%2==0)?'':'im')+'par"></tr>');
                for (var a in map) {
                    val = rows[i][a];
                    if (map[a].key) {
                        key.push(val);
                        if (!map[a].show) continue;
                    }
                    attr = map[a].align || 'left';
                    tr.append($('<td style="text-align:'+attr+';">'+val+'</td>'));
                }
                if (key.length==0) key.push (i);
                tr.attr("id", key.join('&'));
                attr = rows[i]['_control'] || '';
                if (attr)
                    tr.attr("control", attr);
                tbody.append(tr);
            }
            tbody.children('tr').click(function (e){
               var target = $(e.target).parent();
               var options = target.parent().parent().data('options');
               if (options.control)
                    options.control.apply(target);
               $('tr', target.parent()).removeClass('highlight');
               target.addClass('highlight');
            });
        },
        control: function (options) {
            var fix;
            var target = $(this);
            options.parent = options.parent || 'table';
            options.height = options.height || 50;
            options.buttonHeight = options.buttonHeight || 22;
            options.labelHeight = options.labelHeight || 14;
            options.fontSize = options.fontSize || 12;
            var table = target.parents(options.parent);
            $("#"+table.attr('id')+"-control.ui-control").fadeOut("slow", function() {
                $(this).remove();
            });
            if (options=='remove')
                return;
            var div = $('<div id="'+table.attr('id')+'-control" class="ui-control" style="position: absolute;"><img src="/images/jquery.lista/flecha.png" style="float: left"><div class="controles"><div class="botones"></div><div class="label"></div></div></div>');
            table.parent().append(div);
            div.css({
                top: target.position().top - (options.height/2) + (target.innerHeight()/2),
                left: table.offset().left + table.innerWidth() + 4,
                width: options.width || '10%',
                "min-height": options.height+'px',
                "line-height": options.height+'px'
            });
            $('.controles', div).css({"min-height" : options.height+"px"});
            $('.controles .botones', div).css({"line-height" : options.buttonHeight+"px"});
            $('.controles .label', div).css({"line-height" : options.labelHeight+"px"}).corner('8px');
            if (options.rule && target.attr('control')) {
                var ul = $('<ul></ul>'), li;
                var controles = target.attr('control').split("");
                for (i in controles) {
                    if (options.rule[controles[i]]) {
                        li = $('<li class="control"><span class="icon"></span></li>');
                        li.attr('label', options.rule[controles[i]].label);
                        li.children('.icon').css('background', "url('"+options.rule[controles[i]].icon+"') no-repeat center center transparent")
                          .hover(function (e){
                                var ts = $(e.target);
                                var label = $('<span>'+ts.parent().attr('label')+'</span>');
                                ts.parents('.botones').siblings('.label').addClass('highlight').append(label);
                                label.css({"font-size" : options.fontSize+"px"}).corner('4px');
                            },
                            function (e){
                                var div = $(e.target).parents('.botones').siblings('.label');
                                div.removeClass('highlight').html('');
                            }
                          ).click(new Function("event", options.rule[controles[i]].action));
                    }
                    ul.append(li);
                }
                $('.botones', div).append(ul);
            }
            div.corner('right corner 1em');
        },
        getData: function () {
            var f, fields = [];
            var ts = $(this);
            var data = ts.data('options');
            var map = ts.data('map');
            for (f in map) {
                fields.push(f);
            }
            data.fields = fields.join(',');
            return data;
        },
        cargar : function (callback) {
            var ts = $(this);
            $.ajax({
                dataType: 'json',
                type: 'post',
                url: ts.data('url'),
                data: ts.lista('getData'),
                success: function (data, xhr, status) {
                    var tbody = ts.children('tbody');
                    tbody.contents().remove();
                    $.fn.lista._fetch.apply(ts, [data.rows]);
                    ts.data("count", data.count);
                    if (callback)
                        callback(ts);
                },
                error: function (xhr, status) {
                    alert(status+' '+xhr.status+': '+xhr.statusText+ '\nUrl: '+ts.data('url'));
                }
            });
            return ts;
        }
    });
})(jQuery);